#include <SDL/SDL_image.h>
# include <math.h>
# include <time.h>
#include <sstream>
#include <iostream>
#include "MainWindow.h"
#include "MiniGame.h"

int const MiniGame::LEFT = 4;
int const MiniGame::RIGHT = 796 - 32;
int const MiniGame::UP = 4;
int const MiniGame::BOTTOM = 668 - 32;

int const MiniGame::piece::FORBIDDEN_LEFT = 224 - 32;
int const MiniGame::piece::FORBIDDEN_RIGHT = 576;
int const MiniGame::piece::FORBIDDEN_UP = 64 - 32;
int const MiniGame::piece::FORBIDDEN_BOTTOM = 448;
int const MiniGame::piece::MAX_LIFE = 50;

MiniGame::piece::piece()
: Life(MiniGame::piece::MAX_LIFE)
{
	do
	{
		double max = (double)MiniGame::RIGHT - 32;
		Position.x = 0 + (int)((double)rand() / ((double)RAND_MAX + 1) * max);
		max = (double)MiniGame::BOTTOM - 32;
		Position.y = 0 + (int)((double)rand() / ((double)RAND_MAX + 1) * max);
	} while ((Position.x >= piece::FORBIDDEN_LEFT - 32 && Position.x <= piece::FORBIDDEN_RIGHT) && (Position.y >= piece::FORBIDDEN_UP - 32 && Position.y <= piece::FORBIDDEN_BOTTOM));
	double max = (double)3;
	do
	{
		directionX = 0 + (int)((double)rand() / ((double)RAND_MAX + 1) * max) - 1;
	} while (directionX == 0);
	directionY = (directionX == -1) ? 1 : -1;

}

MiniGame::explosion::explosion()
{
	Explosion.Surface = IMG_Load("images\\explosion.png");
	Explosion.setTransparence();
	for (int i = 0; i < 25; i++)
	{
		Positions[i].w = 64;
		Positions[i].h = 64;
		Positions[i].x = (i % 5) * 64;
		Positions[i].y = (i / 5) * 64;
	}
	
}

MiniGame::bullet::bullet()
{
	Bullet.Surface = IMG_Load("images\\bullet.png");
	Bullet.setTransparence();
	for (int i = 0; i < 3; i++)
	{
		Positions[i].w = 32;
		Positions[i].h = 32;
		Positions[i].x = 32 * i;
		Positions[i].y = 0;
	}
}

MiniGame::bullets::bullets()
{
	for (int i = 0; i < BULLETS; i++)
	{
		Positions[i].w = 0;
		Positions[i].h = 0;
		Positions[i].x = 0;
		Positions[i].y = 0;
		Ptr[i] = NULL;
		Lifes[i] = MiniGame::piece::MAX_LIFE / 2;
	}
}

MiniGame::MiniGame(SDL_Surface* _screen)
: m_screen(_screen), m_level(0), m_nbPieces(0), m_nbDead(0), m_speed(1), m_pieces(NULL), m_mitraillette(false), m_score(0), m_lastScore(0), m_showScore(false)
{
	m_digital = TTF_OpenFont("fonts\\digital-7.ttf", 20);
	m_piece.Surface = IMG_Load("images\\SelectedPiece.png");
	m_piece.setTransparence();
	m_cursor.Surface = IMG_Load("images\\SelectedCaseCursor.png");
	m_cursor.setTransparence();
	this->initLevel(0);
	SDL_Color fg = {255, 0, 0};
	m_scoreText.Surface = TTF_RenderText_Solid(m_digital, "0", fg);
	m_scoreText.Position.y = 425;
		m_scoreText.Position.x = 570 - m_scoreText.Surface->w;
}

MiniGame::~MiniGame()
{
	if (m_pieces != NULL)
		delete [] m_pieces;
	TTF_CloseFont(m_digital);
}

void MiniGame::initLevel(int _level)
{
	if (_level > 10)
		_level = 10;
	if (m_pieces != NULL)
		delete [] m_pieces;
	m_nbPieces = 1 << m_level;
	srand((unsigned)time(NULL));
	m_pieces = new piece[m_nbPieces];
	m_speed = m_level / 2 + 2;
	m_nbDead = 0;
	m_mitraillette = false;
	for (int i = 0; i < BULLETS; i++)
	{
		m_bullets.Positions[i].w = 0;
		m_bullets.Positions[i].h = 0;
		m_bullets.Positions[i].x = 0;
		m_bullets.Positions[i].y = 0;
		m_bullets.Ptr[i] = NULL;
		m_bullets.Lifes[i] = MiniGame::piece::MAX_LIFE / 2;
	}
}

void MiniGame::drawPieces()
{
	for (int i = 0; i < m_nbPieces; i++)
	{
		if (m_pieces[i].Life != MiniGame::piece::MAX_LIFE && m_pieces[i].Life > 0)
			SDL_BlitSurface(m_explosion.Explosion.Surface, &m_explosion.Positions[(MiniGame::piece::MAX_LIFE / 2) - (m_pieces[i].Life / 2)], m_screen, &m_pieces[i].Position);
		else if (m_pieces[i].Life == MiniGame::piece::MAX_LIFE)
			SDL_BlitSurface(m_piece.Surface, NULL, m_screen, &m_pieces[i].Position);
	}
}

void MiniGame::drawCursor()
{
	int x = 0, y = 0;
	SDL_GetMouseState(&x, &y);
	if (!(x > MiniGame::piece::FORBIDDEN_LEFT + 16 && x < MiniGame::piece::FORBIDDEN_RIGHT + 16
		&& y > MiniGame::piece::FORBIDDEN_UP + 16 && y < MiniGame::piece::FORBIDDEN_BOTTOM + 16))
	{
		SDL_BlitSurface(m_cursor.Surface, NULL, m_screen, &m_cursor.Position);
		SDL_ShowCursor(0);
	}
	else
		SDL_ShowCursor(1);
}

void MiniGame::draw()
{
	for (int i = 0; i < BULLETS; i++)
	{
		if (m_bullets.Ptr[i] != NULL)
		{
			int frame = ((MiniGame::piece::MAX_LIFE / 2) / m_bullets.Lifes[i]);
			if (frame >= 0 && frame < 3)
				SDL_BlitSurface(m_bullets.Ptr[i], &m_bullet.Positions[frame], m_screen, &m_bullets.Positions[i]);
		}
	}
	this->drawPieces();
	this->drawCursor();
	if (m_showScore == true)
		SDL_BlitSurface(m_scoreText.Surface, NULL, m_screen, &m_scoreText.Position);
}

void MiniGame::movePieces(int i)
{
	int offsetx = m_pieces[i].directionX * m_speed;
	int offsety = m_pieces[i].directionY * m_speed;
	int x = m_pieces[i].Position.x + offsetx;
	int y = m_pieces[i].Position.y + offsety;
	if (x + offsetx <= MiniGame::LEFT|| x + offsetx >= MiniGame::RIGHT
		|| (x + offsetx > MiniGame::piece::FORBIDDEN_LEFT && x < MiniGame::piece::FORBIDDEN_RIGHT && y > MiniGame::piece::FORBIDDEN_UP && y < MiniGame::piece::FORBIDDEN_BOTTOM)
		|| (x + offsetx < MiniGame::piece::FORBIDDEN_RIGHT && x > MiniGame::piece::FORBIDDEN_RIGHT && y > MiniGame::piece::FORBIDDEN_UP && y < MiniGame::piece::FORBIDDEN_BOTTOM))
	{
		m_pieces[i].directionX *= -1;
		x = m_pieces[i].Position.x + (offsetx * -1);
	}
	if (y + offsety <= MiniGame::UP || y >= MiniGame::BOTTOM
		|| (y + offsety > MiniGame::piece::FORBIDDEN_UP && y < MiniGame::piece::FORBIDDEN_BOTTOM && x > MiniGame::piece::FORBIDDEN_LEFT && x < MiniGame::piece::FORBIDDEN_RIGHT)
		|| (y + offsety < MiniGame::piece::FORBIDDEN_BOTTOM && y > MiniGame::piece::FORBIDDEN_UP && x > MiniGame::piece::FORBIDDEN_LEFT && x < MiniGame::piece::FORBIDDEN_RIGHT))
	{
		m_pieces[i].directionY *= -1;
		y = m_pieces[i].Position.y + (offsety * -1);
	}
	m_pieces[i].Position.x = x;
	m_pieces[i].Position.y = y;
}

void MiniGame::piecesEvent(int& nbDead)
{
	for (int i = 0; i < m_nbPieces; i++)
	{
		if (m_pieces[i].Life != MiniGame::piece::MAX_LIFE && m_pieces[i].Life > 0)
			m_pieces[i].Life--;
		else if (m_pieces[i].Life <= 0)
		{
			m_pieces[i].Life = 0;
			nbDead++;
		}
		else if (m_pieces[i].Life == MiniGame::piece::MAX_LIFE)
		{
			this->movePieces(i);	
		}
	}
}

void MiniGame::checkMitraillette(bool& _clicked)
{
	SDL_Event& e = MainWindow::Event();
	if (e.button.button == SDL_BUTTON_RIGHT)
	{
		if (e.type == SDL_MOUSEBUTTONDOWN)
			m_mitraillette = true;
		else if (e.type == SDL_MOUSEBUTTONUP)
			m_mitraillette = false;
	}
	else
		_clicked = (e.type == SDL_MOUSEBUTTONDOWN);
}

void MiniGame::clickEvent(int x, int y)
{
	bool clicked = false;
	m_cursor.Position.x = x - 16;
	m_cursor.Position.y = y - 16;
	this->checkMitraillette(clicked);
	if (m_mitraillette || clicked)
	{
		for (int i = 0; i < BULLETS; i++)
		{
			if (m_bullets.Ptr[i] == NULL)
			{
				m_bullets.Positions[i].x = m_cursor.Position.x;
				m_bullets.Positions[i].y = m_cursor.Position.y;
				m_bullets.Ptr[i] = m_bullet.Bullet.Surface;
				m_bullets.Lifes[i]--;
				break ;
			}
					
		}
		bool fail = false;
		for (int i = 0; i < m_nbPieces; i++)
		{
			if (m_pieces[i].Life != MiniGame::piece::MAX_LIFE)
				continue ;
			SDL_Rect area = { m_pieces[i].Position.x + 4, m_pieces[i].Position.y + 4, m_piece.Surface->w - 4, m_piece.Surface->h - 4 };
			if (x >= area.x && x <= area.x + area.w && y >= area.y && y <= area.y + area.h)
			{
				m_pieces[i].Life--;
				m_score += 10;
			}
			else if (fail == false)
			{
				if (m_score > 0)
					m_score--;
				fail = true;
			}
			if (m_showScore == false)
				m_showScore = true;
		}
	}
}

void MiniGame::doEvents()
{
	if (m_score != m_lastScore)
	{
		SDL_FreeSurface(m_scoreText.Surface);
		SDL_Color fg = {255, 0, 0};
		std::stringstream oss;
		oss << m_score;
		m_scoreText.Surface = TTF_RenderText_Solid(m_digital, oss.str().c_str(), fg);
		m_lastScore = m_score;
		m_scoreText.Position.x = 570 - m_scoreText.Surface->w;
	}
	for (int i = 0; i < BULLETS; i++)
	{
		if (m_bullets.Ptr[i] != NULL)
		{
			m_bullets.Lifes[i]--;
			if (m_bullets.Lifes[i] == 0)
			{
				m_bullets.Lifes[i] = MiniGame::piece::MAX_LIFE;
				m_bullets.Ptr[i] = NULL;
			}
		}
	}
	//std::cout << nbDead << std::endl;
	int nbDead = 0;
	this->piecesEvent(nbDead);
	if (nbDead == m_nbPieces)
	{
		m_level++;
		if (m_level > 10)
			m_level = 0;
		this->initLevel(m_level);
		return ;
	}

	int x = 0, y = 0;
	Uint8 click = SDL_GetMouseState(&x, &y);
	if (!(x > MiniGame::piece::FORBIDDEN_LEFT + 16 && x < MiniGame::piece::FORBIDDEN_RIGHT + 16
		&& y > MiniGame::piece::FORBIDDEN_UP + 16 && y < MiniGame::piece::FORBIDDEN_BOTTOM + 16)
		&& x >= 16 && x <= 786 && y >= 16 && y <= 656)
	{
		this->clickEvent(x, y);
	}
}
